import TaskQueue
import threading
import config as config
import logUtil
import logging
import taskmodel as taskmodel
import api as runs
import psutil
import errorcode
import TensorflowTaskQueue
from dbtool import Dao
import time

# 每个任务线程
class WorkBackendThread(threading.Thread):
    def __init__(self, work_queue,se):
        super().__init__()
        self.work_queue = work_queue
        self.daemon = True
        self.se = se

    def run(self):

        self.se.acquire()
        ##获取队列对象
        # 停留2秒两个作用：
        # 1.避免java后于python修改task为quening的状态
        # 2. 避免任务还没加入队列就开了新的线程
        time.sleep(2)

        item = self.work_queue.pop()
        if item != None:
            if (item.get_state() == 0):
                #task_id
                task_id = item.get_task_id()
                #日志初始化
                log_name, log_path, file = logUtil.set_log(task_id)
                item.set_log_name(log_name)
                item.set_log_path(log_path)
                try:
                    runs.train_model(self,task_info=item)
                except Exception as e:
                    logging.error(errorcode.Model_Train_1 + ':' + str(e))
                    item.set_state(3)# 保证队列不进入死循环
                #移除log
                logging.getLogger().removeHandler(file)
        self.se.release()

# 每个tensorflow任务排队
class TensorflowWorkBackendThread(threading.Thread):
    def __init__(self, tensorflowtaskqueue,status,se):
        super().__init__()
        self.tensorflowtaskqueue = tensorflowtaskqueue
        self.daemon = True
        self.status = status
        self.se = se
    def run(self):
        ##获取队列对象
        # 停留2秒两个作用：
        # 1.避免java后于python修改task为quening的状态
        # 2. 避免任务还没加入队列就开了新的线程
        self.se.acquire()
        time.sleep(2)
        if self.status == 0:
            while self.tensorflowtaskqueue.getItem(0):
                item = self.tensorflowtaskqueue.getItem(0)
                if item != None:
                    if (item.get_state() == 0):
                        #task_id
                        task_id = item.get_task_id()
                        print('--------------------正在执行任务%s--------------------'%task_id)
                        #日志初始化
                        log_name, log_path, file = logUtil.set_log(task_id)
                        item.set_log_name(log_name)
                        item.set_log_path(log_path)
                        try:
                            runs.train_model(self,task_info=item)
                        except Exception as e:
                            logging.error(errorcode.Model_Train_1 + ':' + str(e))
                            item.set_state(3)# 保证队列不进入死循环
                        #移除log
                        logging.getLogger().removeHandler(file)
                        time.sleep(2)
                self.tensorflowtaskqueue.pop()
                print('执行任务完成，当前TensorFlow队列还有%d个任务，准备进行下个任务'%self.tensorflowtaskqueue.count())
        else:
            pass
        self.se.release()


class trainMachineState(object):
    def __init__(self):
        self.gpunum = config.train_default_gpunum
        self.taskqueue = TaskQueue.TaskQueue()
        self.tensorflowtaskqueue = TensorflowTaskQueue.TensorflowTaskQueue()
        self.workertate = 0
        self.classytime = config.train_default_classy_costtime
        self.detecttime = config.train_default_detect_costtime
        # self.startAllTaskList()
        self.status = 0
        self.train_threading_num = config.train_threading_num
        self.semaphore = threading.BoundedSemaphore(self.train_threading_num)

    def checkIllage(self, taskdata):
        if not ('taskid' in taskdata.keys()):
            return 0
        if not ('fileid' in taskdata.keys()):
            return 0
        return 1

    def addTask(self, taskdata):

        myresponse = dict()
        tasklist = self.taskqueue.getList()
        print('线程队列长度为：', self.tensorflowtaskqueue.count())
        if self.tensorflowtaskqueue.count() == 0:
            print('---------------更改状态为0---------------')
            self.status = 0
        else:
            print('---------------更改状态为1---------------')
            self.status = 1

        if tasklist.__len__() > 50:
            myresponse['ret'] = 202004
            myresponse['msg'] = config.Eval_Msg_Add_202004
            return myresponse
        if self.checkIllage(taskdata):
            tasklist = self.taskqueue.getList()
            for i in range(0, len(tasklist)):
                task = self.taskqueue.getItem(i)
                if task == None:
                    continue
                if taskdata["taskid"] == task.get_task_id(): #将get_taskid改为task_id
                    myresponse['ret'] = 10004
                    myresponse['msg'] = config.Eval_Msg_Add_10004
                    return myresponse
            taskid=taskdata["taskid"]
            calibration_set_id=taskdata["fileid"]
            project_id = taskdata["projectid"]
            project_type = taskdata['projectType']
            # file_name = taskdata['fileName']
            # file_size = taskdata['fileSize']
            #newtaskworker = taskmodel.TaskModel(calibration_set_id=calibration_set_id,  task_id=taskid, project_id=project_id, file_name = file_name, file_size = file_size)
            newtaskworker = taskmodel.TaskModel(calibration_set_id=calibration_set_id, task_id=taskid, project_id=project_id)

            # 封装队列对象
            #newtaskworker = taskmodel.TaskModel(model_type='分类', model_name='逻辑回归', task_id=taskid)
            if project_type == 'img_detection':
                self.tensorflowtaskqueue.put(newtaskworker)
                print('添加任务成功，当前TensorFlow队列长度为：',self.tensorflowtaskqueue.count())
            else:
                self.taskqueue.put(newtaskworker)  # 放进队列里面
            myresponse['ret'] = 0
            myresponse['msg'] = config.Train_Msg_Add_0
            # dao = Dao()
            # task_update_limit = {'id': taskid}  # 查询条件
            # task_update_status = {'status': 'queuing'}
            # dao.update_from_dict('training_task', task_update_status, task_update_limit)
            return myresponse
        else:
            myresponse['ret'] = 10003
            myresponse['msg'] = config.Train_Msg_Add_10003
            return myresponse
        return myresponse

    def stopTask(self, taskdata):
        myresponse = dict()
        if not ('taskid' in taskdata.keys()):
            myresponse['ret'] = 20003
            myresponse['msg'] = config.Train_Msg_Stop_20003
            return myresponse
        taskid = taskdata['taskid']
        myresponse['ret'] = 20001
        myresponse['msg'] = config.Train_Msg_Stop_20001
        tasklist = self.taskqueue.getList()

        for i in range(0, len(tasklist)):
            task = self.taskqueue.getItem(i)
            if task == None:
                continue

            if taskid == task.task_id: #将taskid改为task_id
                if (task.get_state() == 0):
                    self.taskqueue.delete(i)
                    myresponse['ret'] = 0
                    myresponse['msg'] = config.Train_Msg_Stop_0
                # elif (task.get_state() == 1):
                #     task.stop_train()
                #     myresponse['ret'] = 0
                #     myresponse['msg'] = config.Train_Msg_Stop_0
                else:
                    myresponse['ret'] = 20002
                    myresponse['msg'] = config.Train_Msg_Stop_20002
        return myresponse

    def getTaskList(self):
        myresponse = dict()
        tasklist = self.taskqueue.getList()
        myresponse['tasklist'] = []
        costtime = 0
        for i in range(0, len(tasklist)):
            taskinfo = dict()
            task = self.taskqueue.getItem(i)
            if task == None:
                continue
            if (task.get_state() == 3) or (task.get_state() == 2):
                continue
            # if task.get_type() == 0:
            #     costtime += self.classytime
            # elif task.get_type() == 1:
            #     costtime += self.detecttime
            taskinfo["taskid"] = task.get_task_id()
            taskinfo["state"] = task.get_state()
            taskinfo["waittime"] = 0
            myresponse['tasklist'].append(taskinfo)
        myresponse['ret'] = 0
        myresponse['msg'] = config.Train_Msg_Get_0
        return myresponse

    def startAllTaskList(self,json_data):
        #获取project类型
        project_type = json_data['projectType']
        print(self.status)
        if project_type == 'img_detection' and self.status == 0:
            thread = TensorflowWorkBackendThread(self.tensorflowtaskqueue,self.status,self.semaphore)
            self.status = 1
            # thread.setDaemon(True)#设置线程为后台线程
            thread.start()
        elif project_type != 'img_detection':
            thread = WorkBackendThread(self.taskqueue,self.semaphore)
            # thread.setDaemon(True)#设置线程为后台线程
            thread.start()
            print('线程名称')
            print(thread.getName())
        else:
            pass


    def getWaitTime(self):
        myresponse = dict()
        tasklist = self.taskqueue.getList()
        costtime = 0
        for i in range(0, len(tasklist)):
            task = self.taskqueue.getItem(i)
            if task == None:
                continue
            if (task.get_state() == 3) or (task.get_state() == 2):
                continue
            if task.get_type() == 0:
                costtime += self.classytime
            elif task.get_type() == 1:
                costtime += self.detecttime
        myresponse['ret'] = 0
        myresponse['waittime'] = costtime
        return myresponse

    def getMachineStatus(self):
        myresponse = {}
        try:
            data = psutil.virtual_memory()
            myresponse['percent'] = data.percent
            myresponse['ret'] = 2001
            myresponse['taskNum'] = len(self.taskqueue.getList())
            myresponse['msg'] = config.Machine_Status_Succeeded
        except:
            myresponse['ret'] = 400
            myresponse['msg'] = config.Machine_Status_Failed
        return myresponse